//---------------------------------------------------------------------
// Author: Alex K. Angelopoulos
//
// Description: Class to handle WTSAPI32 API call wrappers.
//
// Creation Date: 2006-09-24
//---------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;

namespace Pscx.Interop
{
    ///<summary>
    /// WtsApi wrappers for wtsapi32.dll (Terminal Services use)
    /// </summary>
    public class TerminalServices
    {
        //private static IntPtr server = IntPtr.Zero;
        //private IntPtr session = IntPtr.Zero;
        private IntPtr _computerHandle = IntPtr.Zero;
        private string _computerName = string.Empty;

        // Specifies the current session (SessionId)
        public const int CURRENT_SESSION = -1;
        public const string ServerNoun = "TerminalServer";
        public const string SessionNoun = "RemoteDesktop";
        public const string ClientNoun = "WinStation";

        public string ComputerName
        {
            get { return this._computerName; }
            set 
            { 
                _computerHandle = OpenServer(value); 
                _computerName = value; 
            }
        }

        public int ConsoleSessionId
        {
            get { return WTSGetActiveConsoleSessionId(); }
        }

        private IntPtr OpenServer(string Server)
        {
            this.CloseServer();
            if (Server.Trim() == String.Empty)
            {
                return System.IntPtr.Zero;
            }
            else
            {
                return WTSOpenServer(Server);
            }
        }

        private void CloseServer()
        {
            if (this._computerHandle != IntPtr.Zero)
            {
                WTSCloseServer(_computerHandle);
            }
        }

        ~TerminalServices()
        {
            // Make sure we close any open handles...
            this.CloseServer();
        }

        public bool LogoffSession(int SessionId, bool wait)
        {
            if (WTSLogoffSession(_computerHandle, SessionId, wait) == 0)
            {
                return false;
            }
            else 
            { 
                return true; 
            }
        }

        public bool DisconnectSession(int SessionId, bool wait)
        {
            if (WTSDisconnectSession(_computerHandle, SessionId, wait) == 0)
            {
                return false;
            }
            else 
            { 
                return true; 
            }
        }

        public bool TerminateProcess(int ProcessId, int ExitCode)
        {
            if (WTSTerminateProcess(_computerHandle, ProcessId, ExitCode) == 0)
            {
                return false;
            }
            else 
            { 
                return true; 
            }
        }

        public bool ShutdownSystem(ShutdownType shutdownFlags)
        {
            if (WTSShutdownSystem(_computerHandle, shutdownFlags) == 0)
            { 
                return false; 
            }
            else 
            { 
                return true; 
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ServerInfo //WTSAPI32: SERVERInfo // WTSAPI32: WTS_SERVER_INFO
        {
            IntPtr pServerName;    // server name
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SessionInfo // WTSAPI32: WTS_SESSION_INFO
        {
            int SessionId;             // session id
            IntPtr WinStationName;      // name of WinStation this session is
            // connected to
            ConnectState State; // connection state (see enum)
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ProcessInfo // WTSAPI32: WTS_PROCESS_INFO
        {
            int SessionId;     // session id
            int ProcessId;     // process id
            string ProcessName; // name of process
            IntPtr UserSid;       // user's SID
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ClientAddress
        {
            int AddressFamily;  // AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
            byte[] Address;    // client network address
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CLIENT_DISPLAY
        {
            int HorizontalResolution; // horizontal dimensions, in pixels
            int VerticalResolution;   // vertical dimensions, in pixels
            int ColorDepth;           // 1 = 16, 2 = 256, 4 = 64K, 8 = 16M
        }

        public enum ConnectState
        {
            Active,              // User logged on to WinStation
            Connected,           // WinStation connected to client
            ConnectQuery,        // In the process of connecting to client
            Shadowing,              // Shadowing another WinStation
            Disconnected,        // WinStation logged on without client
            Idle,                // Waiting for client to connect
            Listening,              // WinStation is listening for connection
            Resetting,               // WinStation is being reset
            Down,                // WinStation is down due to error
            Initializing,                // WinStation in initialization
        }

        public enum WinstationInfo
        {
            InitialProgram,
            ApplicationName,
            WorkingDirectory,
            OEMId,
            SessionId,
            UserName,
            WinStationName,
            DomainName,
            ConnectState,
            ClientBuildNumber,
            ClientName,
            ClientDirectory,
            ClientProductId,
            ClientHardwareId,
            ClientAddress,
            ClientDisplay,
            ClientProtocolType,
        }

        public enum UserConfiguration
        {
            //Initial program settings
            InitialProgram,            // string returned/expected
            WorkingDirectory,          // string returned/expected
            InheritInitialProgram,    // long returned/expected
            AllowLogon,     //long returned/expected
            //Timeout settings
            TimeoutSettingsConnections,    //long returned/expected
            TimeoutSettingsDisconnections, //long returned/expected
            TimeoutSettingsIdle,           //long returned/expected
            //Client device settings
            DeviceClientDrives,       //long returned/expected
            DeviceClientPrinters,         //long returned/expected
            DeviceClientDeaultPrinter,   //long returned/expected
            //Connection settings
            BrokenTimeoutSettings,         //long returned/expected
            ReconnectSettings,             //long returned/expected
            //Modem settings
            ModemCallbackSettings,         //long returned/expected
            ModemCallbackPhoneNumber,      // string returned/expected
            //Shadow settings
            ShadowingSettings,             //long returned/expected
            //User Profile settings
            TerminalServerProfilePath,     // string returned/expected
            //Terminal Server home directory
            TerminalServerHomeDir,       // string returned/expected
            TerminalServerHomeDirDrive,    // string returned/expected
            HomeLocation,
        }

        public enum HomeLocation
        {
            Local = 0,
            Remote = 1
        }

        public enum VirtualChannel
        {
            VirtualClientData,  // Virtual channel client module data
            //     (C2H data)
            VirtualFileHandle
        }

        public enum SendMessageResponse
        {
            //Possible pResponse values from WTSSendMessage()
            Timeout = 32000,
            Asynchronous = 32001
        }

        [Flags]
        public enum ShutdownType
        {
            // Shutdown flags
            Logoff = 0x00000001, // log off all users except
            // current user; deletes WinStations (a reboot is
            // required to recreate the WinStations)
            Shutdown = 0x00000002,  // shutdown system
            Reboot = 0x00000004,  // shutdown and reboot
            PowerOff = 0x00000008, // shutdown and power off (on
            // machines that support power off through software)
            FastReboot = 0x00000010  // reboot without logging users
            // off or shutting down

        }

        [Flags]
        public enum WaitSystemEventFlags
        {
            /* ===================================================================== 
             == EVENT - Event flags for WTSWaitSystemEvent
             ===================================================================== */

            None = 0x00000000, // return no event
            CreatedWinstation = 0x00000001, // new WinStation created
            DeletedWinstation = 0x00000002, // existing WinStation deleted
            RenamedWinstation = 0x00000004, // existing WinStation renamed
            ConnectedWinstation = 0x00000008, // WinStation connect to client
            DisconnectedWinstation = 0x00000010, // WinStation logged on without client
            Disconnected = 0x00000010, // WinStation logged on without client
            LogonUser = 0x00000020, // user logged on to existing WinStation
            LogoffUser = 0x00000040, // user logged off from existing WinStation
            WinstationStateChange = 0x00000080, // WinStation state change
            LicenseChange = 0x00000100, // license state change
            AllEvents = 0x7fffffff, // wait for all event types
            // Unfortunately cannot express this as an unsigned long...
            //FlushEvent = 0x80000000 // unblock all waiters
        }

        public enum Protocol
        {
            // Not an enum in wtsapi32...
            Console = 0,
            Ica = 1,
            Rdp = 2
        }

        /* Flags for Console Notification */
        [Flags]
        public enum Notification
        {
            ThisSession = 0,
            AllSessions = 1
        }

        [DllImport("WtsApi32.dll")]
        public static extern IntPtr WTSOpenServer(string ServerName);

        [DllImport("WtsApi32.dll")]
        public static extern void WTSCloseServer(IntPtr hServer);

        [DllImport("WtsApi32.dll")]
        public static extern int WTSGetActiveConsoleSessionId();

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSEnumerateServers(
            IntPtr pDomainName,
            long Reserved,
            long Version,
            IntPtr ppServerInfo,
            IntPtr pCount);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSEnumerateSessions(
            IntPtr hServer,
            long Reserved,
            long Version,
            IntPtr ppSessionInfo,
            IntPtr pCount);

        [DllImport("WtsApi32.dll")]
        public static extern int WTSEnumerateProcesses(
            IntPtr hServer,
            long Reserved,
            long Version,
            IntPtr ppProcessInfo,
            IntPtr pCount);

        [DllImport("WtsApi32.dll")]
        public static extern int WTSTerminateProcess(
            IntPtr hServer,
            long ProcessId,
            long ExitCode);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSQuerySessionInformation(
            IntPtr hServer,
            long SessionId,
            WinstationInfo info,
            IntPtr ppBuffer,
            IntPtr pBytesReturned);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSQueryUserConfig(
            IntPtr pServerName,
            IntPtr pUserName,
            UserConfiguration WTSConfigClass,
            IntPtr ppBuffer,
            IntPtr pBytesReturned);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSSetUserConfig(
            IntPtr pServerName,
            IntPtr pUserName,
            UserConfiguration WTSConfigClass,
            IntPtr pBuffer,
            long DataLength);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSSendMessage(
            IntPtr hServer,
            long SessionId,
            IntPtr pTitle,
            long TitleLength,
            IntPtr pMessage,
            long MessageLength,
            long Style,
            long Timeout,
            IntPtr pResponse,
            bool bWait);

        [DllImport("WtsApi32.dll")]
        public static extern int WTSDisconnectSession(
            IntPtr hServer,
            long SessionId,
            bool bWait);

        [DllImport("WtsApi32.dll")]
        public static extern int WTSLogoffSession(
            IntPtr hServer,
            long SessionId,
            bool bWait);

        [DllImport("WtsApi32.dll")]
        public static extern int WTSShutdownSystem(
            IntPtr hServer,
            ShutdownType ShutdownFlag);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSWaitSystemEvent(
            IntPtr hServer,
            long EventMask,
            IntPtr pEventFlags);

        [DllImport("WtsApi32.dll")]
        public static extern IntPtr WTSVirtualChannelOpen(
            IntPtr hServer,
            long SessionId,
            IntPtr pVirtualName/* ascii name */);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSVirtualChannelClose(IntPtr hChannelHandle);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSVirtualChannelRead(
            IntPtr hChannelHandle,
            IntPtr TimeOut, 
            IntPtr Buffer,
            IntPtr BufferSize,
            IntPtr pBytesRead);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSVirtualChannelWrite(
            IntPtr hChannelHandle,
            IntPtr Buffer, 
            IntPtr Length,
            IntPtr pBytesWritten);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSVirtualChannelPurgeInput(IntPtr hChannelHandle);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSVirtualChannelPurgeOutput(IntPtr hChannelHandle);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSVirtualChannelQuery(
            IntPtr hChannelHandle,
            VirtualChannel wtsvirtualclass,
            IntPtr ppBuffer,
            IntPtr pBytesReturned);

        [DllImport("WtsApi32.dll")]
        public static extern void WTSFreeMemory(IntPtr pMemory);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSRegisterSessionNotification(IntPtr handle, long dwFlags);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSUnRegisterSessionNotification(IntPtr handle);

        [DllImport("WtsApi32.dll")]
        public static extern bool WTSQueryUserToken(IntPtr SessionId, IntPtr phToken);
    }
}
